/***
 *
 * 一个用于实现鼠标框选物体的类 Region.js
 *
 * Daniel
 *
 * 2018.03.28
 *
 * **/
define([],function(){
    var Region = function(){
        this.world = {};
        this.dom = {};
        this.rectangle = {};
        this.camera = {};
        
        this.startX = "";
        this.startY = "";
        
        this.enable = false;
        this.flag = false;
        this.domId = "box";
    
        this.color = "#fbbc05";
        this.border = 2;
        
    
    };
    //私有属性和方法
    
    var scope,flag,lab;
    
    //初始化参数
    Region.prototype.init = function(world){
        //执行代码
        this.world = world;
        this.container = world.container;
        this.camera = world.camera;
        this.enable = true;
        flag = this.flag;
        scope = this;
    };
    
   
    //生成3D选框
    Region.prototype.drawBox = function(event){
        //执行代码
        if(event){
        
            
            
            
        }
        
    };
    
    //计算当前的模型
    Region.prototype.computeModel = function(){
        //执行代码
        
        
        
    };
    
    //
    
    //清除绘制
    Region.prototype.dispose = function(){
        //执行代码
        document.removeEventListener("mousedown",mouseDown,false);
        document.removeEventListener("mousemove",mousemove,false);
        document.removeEventListener("mouseup",mouseup,false);
        
        
    };
    
    //激活绘制二维框
    Region.prototype.start = function(){
        //执行代码
    
        document.addEventListener("mousedown",mouseDown,false);
        document.addEventListener("mousemove",mousemove,false);
        document.addEventListener("mouseup",mouseup,false);
    
    
    };
    
    
    //绘制二维框
    function mouseDown(event){
        if(scope.enabled === false)return;
        if(event && event.ctrlKey){
            var div;
            scope.dom= document.createElement("div");
            div =  scope.dom;
            scope.startX = event.clientX ;
            scope.startY = event.clientY ;
            scope.world.camera.orbitControls.enabled = false;
            div.id = scope.domId;
            div.style.cssText = "position:absolute; " +
                "border:"+scope.border+"px dashed "+scope.color+"; " +
                "width:0px; height:0px;" +
                "left:0px; top:0px; " +
                "overflow:hidden;";
            div.style.marginLeft = scope.startX + "px";
            div.style.marginTop = scope.startY + "px";
            document.body.appendChild(div);
            flag = true;
        }
        
    }
    
    
    //
    function mouseup(event) {
        if(scope.enabled === false)return;
        if(event){
            if(flag){
                if(event.ctrlKey && lab){
                    detectionModel(event);
                    lab = false;
                }
                removeDom();
            }
         
        }
    }
    
    //
    function mousemove(e) {
        if(scope.enabled === false)return;
        if(e){
            if(!e.ctrlKey){
                removeDom();
            }
            if(flag && e.ctrlKey){
                try{
                    var evt = window.event || e;
                    var units = "px";
                    var retcLeft = (scope.startX - evt.clientX  > 0 ? evt.clientX : scope.startX);
                    var retcTop = (scope.startY - evt.clientY  > 0 ? evt.clientY  : scope.startY);
                    var retcHeight = Math.abs(scope.startY - evt.clientY );
                    var retcWidth = Math.abs(scope.startX - evt.clientX );
                    lab = true;
                    scope.dom.style.marginLeft = retcLeft + units;
                    scope.dom.style.marginTop = retcTop + units;
                    scope.dom.style.width = retcWidth + units;
                    scope.dom.style.height = retcHeight + units;
                }catch(e){
                }
            }
        }
        
    }
    
    //检测选区内的模型
    function detectionModel(event) {
        var box = modelBox(event);
        var box3 = new THREE.Box3();
        box3.setFromObject(box);
        
        
    }
    
    
    //生成选取框
    function modelBox(event){
        var vexters = computeVertex(event);
        var model = new computeBoundingBox(vexters);
        var material = new THREE.MeshPhongMaterial({
            opacity : 0.7,
            transparent : true,
            side:2
        });
        var mesh = new THREE.Mesh(model,material);
            mesh.position.addVectors(vexters[0],vexters[vexters.length-1]).multiplyScalar(0.5);
    
        return mesh;
    }
    
   
    
    //清楚二维框
    function removeDom(){
        var object = document.getElementById(scope.domId);
        if(object == undefined)return;
        document.body.removeChild(object);
        flag = false;
        scope.world.camera.orbitControls.enabled = true;
        scope.rectangle = {};
    }
    
    //计算三维顶点
    function computeVertex(event){
        var startX,startY,endX,endY,
            VertexA,VertexB,VertexC,VertexD,
            VectorA,VectorB,VectorC,VectorD,
            normaA,normaB,
            projectA,projectB,projectC,projectD;
    
        startX = scope.startX;
        startY = scope.startY;
        endX = event.clientX;
        endY = event.clientY;
        
        //确定二维顶点
        VertexA = new THREE.Vector2(startX,startY);
        VertexB = new THREE.Vector2(endX,startY);
        VertexC = new THREE.Vector2(startX,endY);
        VertexD = new THREE.Vector2(endX,endY);
    
        //计算三维顶点
        VectorA = transformCoord(VertexA);
        VectorB = transformCoord(VertexB);
        VectorC = transformCoord(VertexC);
        VectorD = transformCoord(VertexD);
    
        //计算平面法向量
        normaA = planeNormal(VectorA,VectorB,VectorC);
        normaB = planeNormal(VectorB,VectorC,VectorD);
        
        //计算三维顶点映射
        projectA =  projectVector(normaA,VectorA);
        projectB =  projectVector(normaA,VectorB);
        projectC =  projectVector(normaB,VectorC);
        projectD =  projectVector(normaB,VectorD);
       return [projectB,projectA,projectC,projectD,VectorB,VectorD,VectorA,VectorC];
    }
    
    //坐标转换器
    function transformCoord(vertex){
        
        var vector  = new THREE.Vector3(
            (vertex.x/window.innerWidth)*2 - 1,
            -(vertex.y/window.innerHeight)*2 + 1,
            0.9991768808132582
        );
        vector.unproject(scope.camera);
        return vector;
    }
    
    //计算平面法向量
    function planeNormal(v1,v2,v3){
        var  vec1 = new THREE.Vector3();
        vec1.x = v2.x - v1.x;
        vec1.y = v2.y - v1.y;
        vec1.z = v2.z - v1.z;
    
        var vec2 = new THREE.Vector3();
        vec2.x = v3.x - v1.x;
        vec2.y = v3.y - v1.y;
        vec2.z = v3.z - v1.z;
    
        var vec  = new THREE.Vector3();
        vec.x = vec1.y * vec2.z - vec1.z * vec2.y;
        vec.y = vec1.z * vec2.x - vec1.x * vec2.z;
        vec.z = vec1.x * vec2.y - vec1.y * vec2.x;
    
        var  d = vec.length();
        vec.x = vec.x/d;vec.y = vec.y/d;vec.z = vec.z/d;
        vec.multiplyScalar(-1);
        return vec;
    }
    
    //计算映射点
    function projectVector(normal,vector){
    var newVector = normal.clone();
    var vectors = vector.clone();
        vectors.projectOnPlane(newVector);
        return vectors;
    
    }
    
    //计算集合模型
    function comeputMesh(indices,vertices){
        THREE.BufferGeometry.call(this);
        this.type = 'meshBox';
        this.setIndex(indices);
        this.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
        
    }
    comeputMesh.prototype = Object.create(THREE.BufferGeometry.prototype);
    comeputMesh.prototype.constructor = comeputMesh;
    
    //计算当前的模型
   var computeBoundingBox =  function (array){
        //执行代码
        if(array.length ==0 )return;
        THREE.Geometry.call(this);
        var indexs = [
            0,2,1,2,3,0,
            4,6,5,6,7,5,
            4,6,1,1,4,0,
            7,6,2,2,6,1,
            5,7,3,3,7,2,
            0,3,4,4,5,3
        ];
        var vector = [];
        var len = array.length;
        var i = 0;
        for(i;i<len;i++){
            vector.push(array[i].x,array[i].y,array[i].z);
        }
        this.fromBufferGeometry(new comeputMesh(indexs,vector));
        this.mergeVertices();
        
    };
    computeBoundingBox.prototype = Object.create(THREE.Geometry.prototype);
    computeBoundingBox.prototype.constructor = computeBoundingBox;
    
    return Region;
    
});